Skip to content

clvm_cov: source-level coverage for Chialisp/CLVM - #555

Open
darkverbito wants to merge 1 commit into
Chia-Network:mainfrom
darkverbito:feat/clvm-cov
Open

clvm_cov: source-level coverage for Chialisp/CLVM#555
darkverbito wants to merge 1 commit into
Chia-Network:mainfrom
darkverbito:feat/clvm-cov

Conversation

@darkverbito

@darkverbito darkverbito commented Aug 7, 2026

Copy link
Copy Markdown

Adds clvm_cov, a source-level coverage tool for Chialisp/CLVM, as a new binary alongside run/brun/cldb. Given a corpus of CLVM invocations (program, args), it reports which source lines of each puzzle ran and which stayed cold.

How

It reuses the compiler and cldb. Each source location survives compilation (sha256tree symbols), and cldb resolves every executed step to a Srcloc. clvm_cov compiles each .clsp, builds a sha256tree -> srcloc table, decorates the corpus program and args hex with it, steps the program under CldbRun, and unions the stepped locations. covered = reachable ∩ executed, at (file, line) granularity.

Input / output

The corpus is JSONL, one {program, args, source?, layer?} per line. When source is omitted (a runtime capture sees only program+args), the program is attributed against a global sha256tree -> source table built from every .clsp under --source/--include, uncurrying a curried capture to identify an inner puzzle. Output is LCOV (a union plus one file per layer) and a --summary table: per-file union%, per-layer totals, and the cold worklist.

Granularity

Recompiling honors the source's dialect sigil, so a *standard-cl-25* source compiles optimized and byte-matches an optimized producer's hex; a treehash mismatch warns per source. Non-inline defun branches are line-accurate; inline arms collapse to a shared location.

Files

  • Cargo.toml — declares [[bin]] clvm_cov
  • src/classic/bins/clvm_cov.rs — thin main
  • src/classic/clvm_tools/clvm_cov.rs — driver + unit tests
  • src/classic/clvm_tools/comp_input.rs — adds compile_modern_programs (returns the compiled programs, not the module export summary)
  • src/classic/clvm_tools/mod.rs — registers the module

cargo build --release --bin clvm_cov and the module's 9 unit tests pass.


Note

Medium Risk
Large new tooling surface (~1700 LOC) and a new compile_modern_programs API on the shared compile input path; behavior of existing compile_modern is unchanged but the compiler integration is non-trivial.

Overview
Adds a new clvm_cov binary that reports which .clsp source lines ran vs stayed cold from a JSONL corpus of (program, args) hex invocations.

Coverage reuses the same compile pipeline as run/cldb: build sha256tree → srcloc tables, decorate corpus hex, step with CldbRun, and aggregate reachable ∩ executed at (file, line). Output is LCOV (union plus per-layer files) and an optional --summary with cold-line worklists.

Source-less records (runtime captures without source) compile every .clsp under --source/--include into a global attribution table (parallel compiles via CLVM_COV_JOBS), with curry uncurrying to re-identify inner puzzles and overlay per-source maps when sibling templates share subtrees.

RunAndCompileInputData::compile_modern_programs returns actual compiled program SExps (not module export summaries) so module and multi-export attribution matches on-chain hex.

Reviewed by Cursor Bugbot for commit 8ca0d19. Bugbot is set up for automated code reviews on this repo. Configure here.

Comment thread src/classic/clvm_tools/clvm_cov.rs
Comment thread src/classic/clvm_tools/clvm_cov.rs
A clvm_cov binary, alongside run/brun/cldb, reports which source expressions
of a puzzle a run (or a corpus of runs) executed.

It reuses the compiler and cldb: every source location survives compilation
(sha256tree symbols), and cldb resolves each executed step to a Srcloc.
clvm_cov compiles each .clsp, builds a sha256tree->srcloc table, decorates the
corpus program and args hex with it, steps the program under CldbRun, and
unions the stepped locations. covered = reachable ∩ executed, at (file, line)
granularity.

The corpus is JSONL, one {program, args, source?, layer?} per line. When source
is omitted (a runtime capture sees only program+args), clvm_cov attributes the
program against a global sha256tree->source table built from every .clsp under
--source/--include, uncurrying a curried capture to recover and identify an
inner puzzle. Output is LCOV (a union plus one file per layer) and a --summary
table: per-file union%, per-layer totals, and the cold worklist.

Recompiling honors the source's dialect sigil, so a *standard-cl-25* source
compiles optimized and byte-matches an optimized producer's hex; a treehash
mismatch warns per source. Non-inline defun branches are line-accurate; inline
arms collapse to a shared location.

Adds a [[bin]] clvm_cov (thin main + driver) and compile_modern_programs in
comp_input (returns the compiled programs, not the module export summary).

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 2 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 8ca0d19. Configure here.

if parse_srcloc_string(loc_str).is_some() {
reachable.insert(loc_str.clone());
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Multi-export inflates reachable lines

Medium Severity

For an explicit source pointing at a multi-export module, compile_source unions every export’s symbol table into reachable, and run_corpus adds all of those lines to the denominator. A corpus record whose program hex is only one export still steps just that tree, so sibling exports’ lines appear reachable but never execute and show up as false cold lines and lower union coverage.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 8ca0d19. Configure here.

steps += 1;
}

Ok((executed, matched))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Failed runs report coverage silently

Medium Severity

run_record stops stepping when CldbRun hits RunErr or RunExn, but still returns Ok with a partial executed set. run_corpus merges that into coverage and emits no warning, unlike treehash mismatches, so failed corpus invocations can look like successful partial runs.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 8ca0d19. Configure here.

@prozacchiwawa

Copy link
Copy Markdown
Contributor

will read

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants